import constants from '@/constants';
import { CurrentUser, Public } from '@/decorators';
import {
  AdminCreateDto,
  AdminLoginDto,
  AdminQueryDto,
  AdminRemoveDto,
  AdminUpdateDto,
} from '@/dtos';
import { AdminService } from '@/services/admin.service';
import { compareHash, getNanoid, halt, ok } from '@/utils';
import {
  Body,
  Controller,
  Delete,
  Get,
  Patch,
  Post,
  Query,
} from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import dayjs from 'dayjs';
import { BaseController } from './base.controller';

@Controller('admin')
export class AdminController extends BaseController {
  constructor(
    private readonly jwtService: JwtService,
    private readonly adminService: AdminService,
  ) {
    super();
  }

  @Public()
  @Post('login')
  async login(
    @Body()
    { account, pass }: AdminLoginDto,
  ) {
    let user = await this.adminService.findOne({
      account,
    });

    if (!user) {
      return halt('账号不存在');
    }

    if (!(await compareHash(pass, user.pass))) {
      return halt('密码错误');
    }

    const iss = user.id;
    const jti = await getNanoid();
    const nbf = dayjs().unix();
    const iat = nbf;
    const exp = dayjs().add(15, 'days');

    await this.redis.set(
      `token:admin:${user.id}`,
      jti,
      'EX',
      exp.diff(dayjs(), 'seconds'),
    );

    return ok({
      type: 'Bearer',
      token: await this.jwtService.signAsync({
        id: user.id,
        account: user.account,
        // 编号
        jti,
        // 签发人
        iss,
        // 过期时间
        exp: exp.unix(),
        // 生效时间
        nbf,
        // 签发时间
        iat,
        // 主题
        sub: constants.jwt.subs.admin,
        // 受众
        aud: constants.jwt.auds.admin,
      }),
    });
  }

  @Get('owner')
  async getOwner(@CurrentUser('id') id: number) {
    return ok(
      await this.adminService.findOne(
        {
          id,
          isEnabled: true,
        },
        {
          id: true,
          account: true,
          isSuperAdmin: true,
          mobile: true,
          realname: true,
          avatar: true,
          role: true,
        },
      ),
    );
  }

  @Post('query')
  async query(@Body() dto: AdminQueryDto) {
    return ok(await this.adminService.query(dto));
  }

  @Post('create')
  async create(@Body() dto: AdminCreateDto) {
    return ok(await this.adminService.create(dto.data));
  }

  @Patch('update')
  async update(@Body() dto: AdminUpdateDto) {
    return ok(await this.adminService.update(dto));
  }

  @Delete('remove')
  async remove(@Query() dto: AdminRemoveDto) {
    return ok(await this.adminService.remove(dto));
  }
}
